package com.meiyuetao.myt.finance.entity;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import lab.s2jh.auth.entity.Department;
import lab.s2jh.auth.entity.User;
import lab.s2jh.bpm.BpmTrackable;
import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.entity.annotation.SkipParamBind;
import lab.s2jh.core.web.json.DateJsonSerializer;
import lab.s2jh.core.web.json.DateTimeJsonSerializer;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.envers.NotAudited;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.collect.Lists;
import com.meiyuetao.myt.core.constant.VoucherStateEnum;
import com.meiyuetao.myt.core.constant.VoucherTypeEnum;
import com.meiyuetao.myt.core.entity.MytBaseEntity;

@MetaData("收付款单")
@Entity
@Table(name = "myt_trade_receipt")
@Cache(usage = CacheConcurrencyStrategy.NONE)
public class TradeReceipt extends MytBaseEntity implements BpmTrackable {
    private static final long serialVersionUID = 1L;
    @MetaData(value = "唯一凭证号", tooltips = "创建之后不允许变更")
    private String voucher;
    @MetaData("凭证日期")
    private Date voucherDate;
    @MetaData("凭证状态")
    private VoucherStateEnum voucherState = VoucherStateEnum.DRAFT;
    @MetaData("经办人")
    private User voucherUser;
    @MetaData("经办部门")
    private Department voucherDepartment;

    @MetaData(value = "业务凭证号", comments = "如销售单行项号")
    private String bizVoucher;
    @MetaData("业务凭证类型")
    private VoucherTypeEnum bizVoucherType;

    @MetaData(value = "参考凭证号", comments = "如采购订单，采购单号等")
    private String referenceVoucher;

    private List<TradeReceiptDetail> tradeReceiptDetails = new ArrayList<TradeReceiptDetail>();
    /** 整单付款/收款金额 */
    private BigDecimal totalAmount;
    @MetaData("业务申请付款金额")
    private String bizShouldPayAmount;
    /** 单据类型,FKD付款单,SKD收款单 */
    private VoucherTypeEnum receiptType;
    /** 往来单位 */
    private BizTradeUnit bizTradeUnit;

    @MetaData(value = "结算会计科目")
    private AccountSubject accountSubject;
    @MetaData(value = "记账摘要")
    private String accountSummary;

    @MetaData(value = "关联付款凭证号列表", comments = "逗号分隔，一般用于记录其他三方系统付款的凭证信息")
    private String paymentVouchers;
    @MetaData(value = "付款参考信息", comments = "一般用于记录其他三方系统付款的凭证信息")
    private String paymentReference;
    @MetaData(value = "最近操作摘要")
    private String lastOperationSummary;
    @MetaData(value = "流程当前任务节点")
    private String activeTaskName;
    @MetaData("审核时间")
    private Date auditTime;
    @MetaData("付款时间")
    private Date payTime;
    @MetaData("提交时间")
    private Date submitTime;
    @MetaData("红冲时间")
    private Date redwordDate;

    @JsonProperty
    @Column(length = 128, nullable = false, unique = true, updatable = false)
    public String getVoucher() {
        return voucher;
    }

    public void setVoucher(String voucher) {
        this.voucher = voucher;
    }

    @JsonProperty
    @JsonSerialize(using = DateJsonSerializer.class)
    public Date getVoucherDate() {
        return voucherDate;
    }

    public void setVoucherDate(Date voucherDate) {
        this.voucherDate = voucherDate;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 8, nullable = true)
    @JsonProperty
    public VoucherStateEnum getVoucherState() {
        return voucherState;
    }

    public void setVoucherState(VoucherStateEnum voucherState) {
        this.voucherState = voucherState;
    }

    @ManyToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "voucher_user_id", nullable = false)
    @JsonProperty
    public User getVoucherUser() {
        return voucherUser;
    }

    public void setVoucherUser(User voucherUser) {
        this.voucherUser = voucherUser;
    }

    @ManyToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "voucher_department_id", nullable = false)
    @JsonProperty
    public Department getVoucherDepartment() {
        return voucherDepartment;
    }

    public void setVoucherDepartment(Department voucherDepartment) {
        this.voucherDepartment = voucherDepartment;
    }

    @JsonProperty
    public String getReferenceVoucher() {
        return referenceVoucher;
    }

    public void setReferenceVoucher(String referenceVoucher) {
        this.referenceVoucher = referenceVoucher;
    }

    @OneToMany(mappedBy = "tradeReceipt", cascade = CascadeType.ALL, orphanRemoval = true)
    public List<TradeReceiptDetail> getTradeReceiptDetails() {
        return tradeReceiptDetails;
    }

    public void setTradeReceiptDetails(List<TradeReceiptDetail> tradeReceiptDetails) {
        this.tradeReceiptDetails = tradeReceiptDetails;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getTotalAmount() {
        return totalAmount;
    }

    public void setTotalAmount(BigDecimal totalAmount) {
        this.totalAmount = totalAmount;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 8, nullable = false)
    @JsonProperty
    public VoucherTypeEnum getReceiptType() {
        return receiptType;
    }

    public void setReceiptType(VoucherTypeEnum receiptType) {
        this.receiptType = receiptType;
    }

    @Lob
    @JsonIgnore
    public String getPaymentReference() {
        return paymentReference;
    }

    public void setPaymentReference(String paymentReference) {
        this.paymentReference = paymentReference;
    }

    @OneToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "biz_trade_unit_id", nullable = false)
    @NotAudited
    @JsonProperty
    @ForeignKey(name = "none")
    public BizTradeUnit getBizTradeUnit() {
        return bizTradeUnit;
    }

    public void setBizTradeUnit(BizTradeUnit bizTradeUnit) {
        this.bizTradeUnit = bizTradeUnit;
    }

    @ManyToOne
    @JoinColumn(name = "account_subject_id")
    @JsonProperty
    public AccountSubject getAccountSubject() {
        return accountSubject;
    }

    public void setAccountSubject(AccountSubject accountSubject) {
        this.accountSubject = accountSubject;
    }

    @Transient
    @JsonIgnore
    public void addTradeReceiptDetail(TradeReceiptDetail tradeReceiptDetail) {
        if (tradeReceiptDetails == null) {
            tradeReceiptDetails = Lists.newArrayList();
        }
        tradeReceiptDetails.add(tradeReceiptDetail);
    }

    @JsonProperty
    public String getAccountSummary() {
        return accountSummary;
    }

    public void setAccountSummary(String accountSummary) {
        this.accountSummary = accountSummary;
    }

    @Column(length = 2000)
    @JsonIgnore
    public String getPaymentVouchers() {
        return paymentVouchers;
    }

    public void setPaymentVouchers(String paymentVouchers) {
        this.paymentVouchers = paymentVouchers;
    }

    @JsonProperty
    public String getLastOperationSummary() {
        return lastOperationSummary;
    }

    public void setLastOperationSummary(String lastOperationSummary) {
        this.lastOperationSummary = lastOperationSummary;
    }

    @JsonProperty
    public String getBizShouldPayAmount() {
        return bizShouldPayAmount;
    }

    public void setBizShouldPayAmount(String bizShouldPayAmount) {
        this.bizShouldPayAmount = bizShouldPayAmount;
    }

    @JsonProperty
    @Column(length = 128, nullable = true)
    public String getBizVoucher() {
        return bizVoucher;
    }

    public void setBizVoucher(String bizVoucher) {
        this.bizVoucher = bizVoucher;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 32, nullable = true)
    @JsonProperty
    public VoucherTypeEnum getBizVoucherType() {
        return bizVoucherType;
    }

    public void setBizVoucherType(VoucherTypeEnum bizVoucherType) {
        this.bizVoucherType = bizVoucherType;
    }

    @JsonProperty
    public String getActiveTaskName() {
        return activeTaskName;
    }

    public void setActiveTaskName(String activeTaskName) {
        this.activeTaskName = activeTaskName;
    }

    @Override
    @Transient
    @JsonIgnore
    public String getBpmBusinessKey() {
        return voucher;
    }

    @JsonProperty
    @JsonSerialize(using = DateTimeJsonSerializer.class)
    public Date getAuditTime() {
        return auditTime;
    }

    public void setAuditTime(Date auditTime) {
        this.auditTime = auditTime;
    }

    @JsonProperty
    @JsonSerialize(using = DateTimeJsonSerializer.class)
    public Date getPayTime() {
        return payTime;
    }

    public void setPayTime(Date payTime) {
        this.payTime = payTime;
    }

    @JsonProperty
    @JsonSerialize(using = DateTimeJsonSerializer.class)
    public Date getSubmitTime() {
        return submitTime;
    }

    public void setSubmitTime(Date submitTime) {
        this.submitTime = submitTime;
    }

    public Date getRedwordDate() {
        return redwordDate;
    }

    @SkipParamBind
    public void setRedwordDate(Date redwordDate) {
        this.redwordDate = redwordDate;
    }

    @Override
    @Transient
    public String getExtraInfo() {
        return null;
    }

}
